package org.luxor.commons.lock4j.config;

import org.luxor.commons.lock4j.LockTemplate;
import org.luxor.commons.lock4j.aop.LockAdvisor;
import org.luxor.commons.lock4j.aop.LockInterceptor;
import org.luxor.commons.lock4j.core.LockExecutor;
import org.luxor.commons.lock4j.core.RedisTemplateLockExecutor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * 分布式锁自动配置器
 *
 * @author zengzh TaoYu
 * @since 1.0.0
 */
@Configuration
public class Lock4jConfig {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass(RedisConnectionFactory.class)
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass(RedisTemplate.class)
    public LockExecutor lockExecutor(RedisTemplate redisTemplate) {
        RedisTemplateLockExecutor redisTemplateLockExecutor = new RedisTemplateLockExecutor();
        redisTemplateLockExecutor.setRedisTemplate(redisTemplate);
        return redisTemplateLockExecutor;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass(LockExecutor.class)
    public LockTemplate lockTemplate(LockExecutor lockExecutor) {
        LockTemplate lockTemplate = new LockTemplate();
        lockTemplate.setLockExecutor(lockExecutor);
        return lockTemplate;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass(LockTemplate.class)
    public LockInterceptor lockInterceptor(LockTemplate lockTemplate) {
        LockInterceptor lockInterceptor = new LockInterceptor();
        lockInterceptor.setLockTemplate(lockTemplate);
        return lockInterceptor;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnClass(LockInterceptor.class)
    public LockAdvisor lockAnnotationAdvisor(LockInterceptor lockInterceptor) {
        return new LockAdvisor(lockInterceptor);
    }
}
